//---------------------------------------------------------------------------

#include "vcl_stl.h"
#pragma hdrstop

#include <algorithm>

#include "h_base.h"
#include "h_xml.h"
#include "h_global.h"
#include "h_lz77.h"
using namespace h_base;
using namespace h_xml;

#include "h_server.h"
#include "h_g.h"
#include "t_mainform.h"
#include "h_i18n.h"
//---------------------------------------------------------------------------

static const char *ProtocolVersion = "SIMJIE0104";

bool __fastcall HServer::ReadFileFromSocket(SOCKET Sock,
   char *ErrorStr, const char *FileName)
{
   int r;
   DWORD ErrCode;
   char Buf[8192 + 1];

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
         r, ErrCode);
      return false;
   }

   if ( Buf[0] == '1' )
   {
      r = HComm::Read(Sock, Buf, 8, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
            r, ErrCode);
         return false;
      }
      Buf[8] = '\0';
      int ErrStrLen = h_base::HexStrToInt(Buf);
      if ( ErrStrLen > 200 )
      {
         ErrStrLen = 200;
      }
      r = HComm::Read(Sock, ErrorStr, ErrStrLen, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
            r, ErrCode);
         return false;
      }
      ErrorStr[ErrStrLen] = '\0';
      return false;
   }

   r = HComm::Read(Sock, Buf + 1, 7, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
         r, ErrCode);
      return false;
   }

   Buf[8] = '\0';

   FILE *f = _wfopen(UnicodeString(UTF8String(FileName)).c_str(), L"wb");

   if ( f == NULL )
   {
      snprintf(ErrorStr, 200, h_g::I18nString("h_server:CAN_NOT_CREATE"),
         FileName);
      return false;
   }

   int TotalLen = h_base::HexStrToInt(Buf);

   for( int i = 0; i < TotalLen; )
   {
      int Len;
      if( TotalLen - i >= 1024 )
         Len = 1024;
      else
         Len = TotalLen - i;
      r = HComm::Read(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
            r, ErrCode);
         fclose(f);
         return false;;
      }
      fwrite(Buf, Len, 1, f);
      i += Len;
   }

   fclose(f);
   return true;
}

bool __fastcall HServer::FuncLogin(const UTF8String &Id, const UTF8String &Password,
   const UTF8String &Auth, UTF8String &ErrorString)
{
   const char *PVER = h_g::ServerProtocol == "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "Login", WSAGetLastError());
      goto error;
   }

   r = HComm::Connect(Sock, h_g::ServerIpAddr.c_str(),
      h_g::ServerPort, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
         "Login", h_g::ServerIpAddr.c_str(), h_g::ServerPort, r, ErrCode);
      goto error;
   }

   snprintf(Buf, 8192, "%sA|%s|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Id.c_str(), Password.c_str(), Auth.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "Login", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "Login", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      if ( Buf[0] == '2' )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:ACCESS_DENIED"));
      }
      else
      {
         ErrorString.sprintf(h_g::I18nString("h_server:LOGIN_FAIL"));
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   ShowMessage(ErrorString);
   return false;
}

bool __fastcall HServer::FuncDownload(const UTF8String &SrcFileName,
   const UTF8String &DesFileName)
{
   const char *PVER = h_g::ServerProtocol == "0103" ? "" : ProtocolVersion;

   int TotalLen, Len, i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[4096 + 1];
   HXmlTree Xml;
   string OldTime;
   char TmpFile1[500 + 1];
   char TmpFile2[500 + 1];

   snprintf(TmpFile1, 200, "t1_%ld", GetCurrentProcessId());
   snprintf(TmpFile2, 200, "%s", DesFileName.c_str());

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "Download", WSAGetLastError());
      goto error;
   }

   r = HComm::Connect(Sock, h_g::ServerIpAddr.c_str(),
      h_g::ServerPort, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
         "Download", h_g::ServerIpAddr.c_str(), h_g::ServerPort, r, ErrCode);
      goto error;
   }

   snprintf(Buf, 4096, "%sU|%s|%s|%s|", PVER, h_g::ClientCodeSet.c_str(),
      "", SrcFileName.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:WRITE_ERROR"),
         "Download", r, ErrCode);
      goto error;
   }

   if ( !ReadFileFromSocket(Sock, Buf, TmpFile1) )
   {
      goto error;
   }

   if( !TextFileDecompress(TmpFile1, TmpFile2) )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:TEXT_FILE_DECOMPRESS_FAIL"),
         "Download");
      goto error;
   }

   DeleteFile(TmpFile1);
   closesocket(Sock);
   Sock = INVALID_SOCKET;
   return true;

error :

   DeleteFile(TmpFile1);
   ShowMessage(UTF8String(Buf));

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

#pragma package(smart_init)
